<?php
/**
 * Created by PhpStorm.
 * Author: sitenv@aliyun.com
 * CreateTime: 2023/2/11 14:55
 * Blog：www.myblogs.xyz
 */

namespace app\api\controller;

use app\constants\ResponseCode;
use Illuminate\Support\Facades\Cache;

class CommonController
{
    // 请求参数（必传）
    protected $require = [];
    // 请求参数（非必传）
    protected $selectable = [];
    // 请求参数数据验证
    protected $validate = [];
    protected $data = [];
    protected $userId = 0;
    protected $userData = [];
    protected $httpUrl = '';
    protected $code = '';
    protected $error = '';
    protected $apiKey = '';

    public function __construct()
    {
        // 读取站点配置信息
        $this->apiKey = getenv('API_KEY');
    }

    /**
     * 验证请求参数
     * @param $param
     * @param $method
     * @return bool
     */
    protected function verifyParam($param = [], $method = 'post')
    {
        if ($method == 'post'){
            $requestData = request()->post();
        }else{
            $requestData = request()->get();
        }
        if (empty($requestData)){
            $this->error = '请求错误';
            $this->code = ResponseCode::PARAM_ERR;
            return false;
        }
        if (!empty($param)){
            $this->require = $param;
        }
        if (!empty($this->require)){
            if (is_string($this->require)){
                $this->require = explode(',', $this->require);
            }
        }
        if (!empty($this->selectable)){
            if (is_string($this->selectable)){
                $this->selectable = explode(',', $this->selectable);
            }
        }
        if (!empty($this->require) || !empty($this->selectable)){
            $param = array_merge($this->require, $this->selectable);
            $arrayKeys = array_keys($requestData);
            foreach ($arrayKeys as $key) {
                if (!in_array($key, $param)){
                    unset($requestData[$key]);
                }
            }
            if (!empty($this->require)){
                foreach ($this->require as $val){
                    if (!isset($requestData[$val]) || $requestData[$val] === ''){
                        if (!empty($this->validate[$val])){
                            $this->error = $this->validate[$val];
                        }else{
                            $this->error = '缺少请求参数：' . $val;
                        }
                        $this->code = ResponseCode::PARAM_ERR;
                        return false;
                    }
                }
            }
            $this->data = $requestData;
        }
        return true;
    }

    /**
     * 验证请求头
     * @param bool $require
     * @return bool
     */
    protected function verifyToken($require = true)
    {
        $auth_token = request()->header('Authorization');
        if (empty($auth_token)){
            if ($require){
                $this->error = '缺少请求头Authorization';
                $this->code = ResponseCode::UNAUTH;
                return false;
            }
        }
        $user_token = new UserToken();
        $result = $user_token->tokenAuth(md5($auth_token));
        if (empty($result->user_id)){
            if ($require){
                $this->error = '系统检测到您长时间未登陆，请重新登录';
                $this->code = ResponseCode::UNAUTH;
                return false;
            }
        }else{
            // 获取用户信息
            $user_model = new User();
            $user_fields = 'id,phone,openid,invite_id,status,third_check';
            $user_data = $user_model->getFind($result->user_id, $user_fields);
            if (empty($user_data)){
                if ($require) {
                    $this->error = '系统检测到您长时间未登陆，请重新登录';
                    $this->code = ResponseCode::UNAUTH;
                    return false;
                }
            }else{
                $this->data['user_id'] = $user_data->id;
                $this->userId = $user_data->id;
                $this->userData = $user_data;
            }
        }
        return true;
    }

    /**
     * 验证请求频繁
     * @param int $user_id
     * @param int $timeout
     * @return bool
     */
    protected function verifyRequest($user_id = 0, int $timeout = 5)
    {
        if (!$user_id){
            $user_id = $this->userId;
        }
        $limit_key = 'limit_request_'.$user_id;
        $ip = $_SERVER['HTTP_ALI_CDN_REAL_IP'] ?? request()->getRealIp();
        $limit_ip_key = 'limit_ip_'.$ip;
        $limit_account_key = 'limit_account_'.$user_id;
        $limit = Cache::get($limit_key);
        $limit_ip = Cache::get($limit_ip_key);
        $limit_account= Cache::get($limit_account_key);
        if($limit_account > 10){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }
        if($limit_account) {
            Cache::add($limit_account_key, $limit_account + 1, $timeout);
        }else {
            Cache::add($limit_account_key,1, $timeout);
        }
        if($limit){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }else {
            Cache::add($limit_key, $ip, $timeout);
        }
        if($limit_ip){
            $this->error = '操作频繁，请稍后再试';
            $this->code = ResponseCode::FORBIDDEN;
            return false;
        }else{
            Cache::add($limit_ip_key, $user_id, $timeout);
        }
        return true;
    }

    /**
     * 获取请求失败信息
     * @return \support\Response
     */
    protected function verifyError()
    {
        return $this->jsonError($this->error);
    }

    /**
     * 附加参数
     * @param int $code
     * @param array $data
     * @param string $msg
     */
    private function jsonReturn($code = 0, $data = [], $msg = '')
    {
        $result = [
            'msg'  => $msg,
            'code' => $code,
            'data' => $data,
        ];
        return json($result);
    }

    /**
     * 请求验证失败
     * code 9999：请求验证失败
     * @param string $msg
     * @param array $data
     */
    protected function jsonFail($msg = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::FORBIDDEN, (object)$data, $msg);
    }

    /**
     * 操作数据成功
     * code 1000：操作数据成功；可能有数据返回对象形式
     * @param string $msg
     * @param array $data
     */
    protected function jsonSuccess($msg = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::SUCCESS, (object)$data, $msg);
    }

    /**
     * 操作数据失败
     * code 1001：操作数据失败
     * @param string $msg
     * @param array $data
     */
    protected function jsonError($msg = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::PARAM_ERR, (object)$data, $msg);
    }

    /**
     * 获取数据成功
     * code 1000：获取数据成功；肯定有数据返回对象数组形式
     * @param array $data
     * @param string $msg
     */
    protected function jsonResult($data = [], $msg = '')
    {
        return $this->jsonReturn(ResponseCode::SUCCESS, $data, $msg);
    }

    /**
     * 没有更多数据
     * code 1001：没有更多数据；空对象数组数据
     * @param array $data
     * @param string $msg
     */
    protected function jsonEmpty($msg = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::SUCCESS, $data, $msg);
    }

    /**
     * TOKEN失效
     * code 1002：TOKEN失效
     * @param array $data
     * @param string $msg
     */
    protected function jsonTokenFailed($msg = '', $data = [])
    {
        return $this->jsonReturn(ResponseCode::UNAUTH, $data, $msg);
    }

    /**
     * 数据日志保存
     * @param $data
     * @param $type
     * @param int $flags
     */
    protected function consoleLog($data, $type = '', $flags = FILE_APPEND)
    {
        $dir = getcwd() . '/runtime/api/';
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        $html = '';
        $filename = $dir . $type . date('YmdH') . '.html';
        if (!file_exists($filename)){
            $html .= '<!DOCTYPE html><html><head>';
            $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
            $html .= '</head><body>';
        }
        $html .= '<div style="display: inline-block;margin-left: 35%">';
        $html .= '<h5 style="margin: 5px 0">---------------------------------------------------------------</h5>';
        $html .= '<h5 style="margin: 5px 0">执行日期：' . date('Y-m-d H:i:s', time()) . '</h5>';
        $html .= '<h5 style="margin: 5px 0">请求地址：<textarea style="display: inline-block;width: 100%;border: none;font-size: 14px;font-weight: bold;font-family: bold;">' . $this->httpUrl . request()->url() . '</textarea></h5>';
        $html .= '<h5 style="margin: 5px 0">数据信息：<textarea style="display: inline-block;width: 100%;border: none;font-size: 14px;font-weight: bold;font-family: bold;">' . json_encode($data) . '</textarea></h5>';
        $html .= '</div>';
        if (!file_exists($filename)){
            $html .= '</body></html>';
        }
        file_put_contents($filename , $html, $flags);
    }

}